/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <atomic>
#include <memory>
#include "utils_noncopyable.h"
#include "common_media_define.h"
#include "media_frame.h"
#include "utils_callback_list.h"
#include "utils_block_queue.h"
#include <thread>

namespace El {
namespace Media {

class StreamSource;
using StreamSourcePtr = std::shared_ptr<StreamSource>;

class StreamSource {
    DISALLOW_COPY_AND_MOVE(StreamSource);

public:
    using Proc = std::function<void(const MediaFramePtr &)>;

    static StreamSourcePtr Create(int32_t ch, int32_t type);

    StreamSource(int32_t ch, int32_t type);

    ~StreamSource();

    bool SetInfo(int32_t listSize, std::string name);

    // 启动流媒体
    int32_t Start();

    // 停止流媒体
    void Stop();

    // 注册回调函数
    // 支持支持GetFrame和Register两种的一种方式，互斥
    int32_t Register(const Proc &proc);

    // 取消注册回调函数
    void Unregister(int32_t handle);

    // 获取一帧数据
    // 支持支持GetFrame和Register两种的一种方式，互斥
    MediaFramePtr GetFrame(int32_t timeout);

    // 强制I帧
    bool ForceIframe();

private:
    void StreamThread();

private:
    int32_t ch_{0};
    int32_t type_{0};
    bool start_{false};
    bool waitForIFrame_{true};
    std::mutex mutex_;

    Utils::CallbackList<void, const MediaFramePtr &> callbackManager_;

    int32_t streamHandle_{0};
    int32_t streamAudioHandle_{0};

    std::unique_ptr<Utils::BlockingQueue<Media::MediaFramePtr>> queue_;
    std::unique_ptr<std::thread> streamThread_;

    int32_t max_{10};
    std::string name_{"stream media data"};
};

} // namespace Media
} // namespace El